#include "common.hpp"

// 程序加载时自动构建全局对象 -- 调用构造函数创建管道文件
// 程序退出时自动析构全局对象 -- 调用析构函数删除管道文件
Init init;

int main()
{
    // 1. 创建公共的Key值
    key_t k = ftok(PATH_NAME, PROJ_ID);
    assert(k != -1);
    Log("create key done", Debug) << " server key : " << ConvertToHex(k) << endl;

    // 2. 创建shm shm创建成功后会自动全部置0
    // server是通信的发起者 建议创建一个全新的共享内存
    int shmid = shmget(k, SHM_SIZE, IPC_CREAT | IPC_EXCL | 0666);
    if (shmid == -1)
    {
        perror("shmget");
        exit(1);
    }
    Log("create shm done", Debug) << " shmid : " << shmid << endl;
    //sleep(10);

    // 3. 将指定的共享内存 挂接到自己的地址空间
    char *shmaddr = (char *)shmat(shmid, nullptr, 0);
    Log("attach shm done", Debug) << " shmid : " << shmid << endl;
    //sleep(10);

    // 开始进行通信 将共享内存看成一个大字符串 char buffer[SHM_SIZE];
    int fd = OpenFIFO(FIFO_NAME, READ);
    while (true)
    {
        Wait(fd); // 从命名管道中读取数据 没有数据则阻塞等待；只有当客户端向shm中写入数据并向命名管道中写入数据后才会唤醒
        // 临界区：100行代码只有几行访问共享资源的代码
        printf("%s\n", shmaddr);
        if (strcmp(shmaddr, "quit") == 0)
            break;
    }
    CloseFifo(fd);

    // 4. 将指定的共享内存 从自己的地址空间中删除映射
    int n = shmdt(shmaddr);
    assert(n != -1);
    (void)n;
    Log("detach shm done", Debug) << " shmid : " << shmid << endl;
    //sleep(10);

    // 5. 删除共享内存 IPC_RMID: 即便是有进程和当下的shm挂接 依旧删除共享内存
    n = shmctl(shmid, IPC_RMID, nullptr);
    assert(n != -1);
    (void)n;
    Log("delete shm done", Debug) << " shmid : " << shmid << endl;

    return 0;
}